/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package DAO;

import DAO.exceptions.NonexistentEntityException;
import DAO.exceptions.PreexistingEntityException;
import java.io.Serializable;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import Entidad.Actor;
import Entidad.Movie;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;

/**
 *
 * @author USUARIO
 */
public class MovieJpaController implements Serializable {

    public MovieJpaController(EntityManagerFactory emf) {
        this.emf = emf;
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Movie movie) throws PreexistingEntityException, Exception {
        if (movie.getActors() == null) {
            movie.setActors(new ArrayList<Actor>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            List<Actor> attachedActors = new ArrayList<Actor>();
            for (Actor actorsActorToAttach : movie.getActors()) {
                actorsActorToAttach = em.getReference(actorsActorToAttach.getClass(), actorsActorToAttach.getName());
                attachedActors.add(actorsActorToAttach);
            }
            movie.setActors(attachedActors);
            em.persist(movie);
            for (Actor actorsActor : movie.getActors()) {
                actorsActor.getMovies().add(movie);
                actorsActor = em.merge(actorsActor);
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            if (findMovie(movie.getName()) != null) {
                throw new PreexistingEntityException("Movie " + movie + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Movie movie) throws NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Movie persistentMovie = em.find(Movie.class, movie.getName());
            List<Actor> actorsOld = persistentMovie.getActors();
            List<Actor> actorsNew = movie.getActors();
            List<Actor> attachedActorsNew = new ArrayList<Actor>();
            for (Actor actorsNewActorToAttach : actorsNew) {
                actorsNewActorToAttach = em.getReference(actorsNewActorToAttach.getClass(), actorsNewActorToAttach.getName());
                attachedActorsNew.add(actorsNewActorToAttach);
            }
            actorsNew = attachedActorsNew;
            movie.setActors(actorsNew);
            movie = em.merge(movie);
            for (Actor actorsOldActor : actorsOld) {
                if (!actorsNew.contains(actorsOldActor)) {
                    actorsOldActor.getMovies().remove(movie);
                    actorsOldActor = em.merge(actorsOldActor);
                }
            }
            for (Actor actorsNewActor : actorsNew) {
                if (!actorsOld.contains(actorsNewActor)) {
                    actorsNewActor.getMovies().add(movie);
                    actorsNewActor = em.merge(actorsNewActor);
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                String id = movie.getName();
                if (findMovie(id) == null) {
                    throw new NonexistentEntityException("The movie with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(String id) throws NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Movie movie;
            try {
                movie = em.getReference(Movie.class, id);
                movie.getName();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The movie with id " + id + " no longer exists.", enfe);
            }
            List<Actor> actors = movie.getActors();
            for (Actor actorsActor : actors) {
                actorsActor.getMovies().remove(movie);
                actorsActor = em.merge(actorsActor);
            }
            em.remove(movie);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Movie> findMovieEntities() {
        return findMovieEntities(true, -1, -1);
    }

    public List<Movie> findMovieEntities(int maxResults, int firstResult) {
        return findMovieEntities(false, maxResults, firstResult);
    }

    private List<Movie> findMovieEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Movie.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Movie findMovie(String id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Movie.class, id);
        } finally {
            em.close();
        }
    }

    public int getMovieCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Movie> rt = cq.from(Movie.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
    
}
